package cn.kxx.serviceImpl;

import cn.kxx.config.RedisUtil;
import cn.kxx.constant.RedisConstant;
import cn.kxx.entity.PageResult;
import cn.kxx.entity.QueryPageBean;
import cn.kxx.exception.BusinessException;
import cn.kxx.mapper.SetMealAndCheckGroupMapper;
import cn.kxx.mapper.SetmealMapper;
import cn.kxx.pojo.Setmeal;
import cn.kxx.pojo.SetmealCheckgroup;
import cn.kxx.service.SetmealService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Service;
import org.apache.ibatis.builder.BuilderException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
public class SetmealServiceImpl implements SetmealService {

    String key = RedisConstant.QUERY_SETMEALS_KEY;
    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private SetMealAndCheckGroupMapper setMealAndCheckGroupMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${out.path}")
    private String outPath;
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Override
    @Transactional
    public void add(Setmeal setmeal, Integer[] checkGroupIds) throws BusinessException {

        //删除缓存

        RedisUtil.delete(redisTemplate, key);
        //检查编码和名称是否重复
        if (checkName(setmeal.getName()) || checkCode(setmeal.getCode())) {
            throw new BuilderException("名称或编码已经存在");
        }
        //添加套餐和关系表
        setmealMapper.insert(setmeal);
        redisTemplate.opsForSet().add(RedisConstant.UPLOAD_SETMEAL_DB_KEY, setmeal.getImg());
        Integer id = setmeal.getId();
        if (checkGroupIds != null && checkGroupIds.length > 0) {
            for (Integer checkGroupId : checkGroupIds) {
                SetmealCheckgroup setmealCheckgroup = new SetmealCheckgroup();
                setmealCheckgroup.setCheckgroupId(checkGroupId);
                setmealCheckgroup.setSetmealId(id);
                setMealAndCheckGroupMapper.insert(setmealCheckgroup);

            }
        }
//        调用新增套餐后重新生成静态界面方法
        //页面静态化
        generateMobileStaticHtml();
    }

    /**
     * 页面静态化
     */
    private void generateMobileStaticHtml() {
        //获取套餐列表
        List<Setmeal> setmealList = this.findAll();
        //静态化套餐列表
        generateMobileSetmealListHtml(setmealList);
        //静态化套餐详情
        generateMobileSetmealDetailHtml(setmealList);
    }

    /**
     * 静态化套餐列表
     * @param setmealList
     */
    private void generateMobileSetmealListHtml(List<Setmeal> setmealList) {
        Map<String,Object> dataMap = new HashMap<>();
        dataMap.put("setmealList", setmealList);
        //页面静态化
        this.generateHtml("mobile_setmeal.ftl", "m_setmeal.html",dataMap);
    }

    /**
     * 静态化套餐详情
     * @param setmealList
     */
    private void generateMobileSetmealDetailHtml(List<Setmeal> setmealList) {
        for (Setmeal setmeal : setmealList) {
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("setmeal", this.findSeteamDetailById(setmeal.getId()));
            this.generateHtml("mobile_setmeal_detail.ftl",
                    "setmeal_detail_"+setmeal.getId()+".html",
                    dataMap);
        }
    }

    /**
     * 页面静态化
     * @param templateName 模板名称
     * @param htmlPageName 页面名称
     * @param dataMap 数据模型
     */
    private void generateHtml(String templateName, String htmlPageName, Map<String,Object> dataMap)  {
        try {
            Configuration configuration = freeMarkerConfigurer.getConfiguration();
            //加载模板
            Template template = configuration.getTemplate(templateName);
            BufferedWriter writer = new BufferedWriter(new FileWriter(outPath + "/" + htmlPageName));
            //页面静态化
            template.process(dataMap, writer);
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("静态化页面失败！");
        }
    }
    //        分页展示
    @Override
    public PageResult findPage(QueryPageBean queryPageBean) throws BusinessException {
        Page<Setmeal> page = new Page<>(queryPageBean.getCurrentPage(), queryPageBean.getPageSize());
        LambdaQueryWrapper<Setmeal> wrapper = null;
        String qstr = queryPageBean.getQueryString();
        if (!StringUtils.isEmpty(qstr)) {
            wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Setmeal::getCode, qstr).or()
                    .like(Setmeal::getName, qstr).or()
                    .eq(Setmeal::getHelpCode, qstr);
        }
        IPage<Setmeal> iPage = setmealMapper.selectPage(page, wrapper);
        return new PageResult(iPage.getTotal(), iPage.getRecords());
    }


    //    查询套餐对应的检查组
    @Override
    public List<Integer> findCheckGroupIdsBySetmealId(Integer id) throws BusinessException {
        List<SetmealCheckgroup> setmealCheckgroups = setMealAndCheckGroupMapper.selectList(
                new LambdaQueryWrapper<SetmealCheckgroup>().eq(SetmealCheckgroup::getSetmealId, id)
        );
        List<Integer> list = new ArrayList<>();
        for (SetmealCheckgroup setmealCheckgroup : setmealCheckgroups) {
            list.add(setmealCheckgroup.getCheckgroupId());
        }
        return list;
    }


    //    查询对应的套餐
    @Override
    public Setmeal findById(Integer id) throws BusinessException {
        return setmealMapper.selectById(id);
    }

    //    编辑套餐
    @Override
    public void edit(Integer[] checkgroupIds, Setmeal setmeal) throws BusinessException {

        if (setmeal == null) {
            throw new BuilderException("套餐信息为空");
        }
        String code = setmeal.getCode();//套餐编码
        String name = setmeal.getName();//套餐名称
        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(name)) {
            throw new BusinessException("套餐名称或编码不能为空");
        }
        //获取原套餐的套餐名称和套餐编码
        Setmeal mySetmeal = findById(setmeal.getId());
        String ocode = mySetmeal.getCode();
        String oname = mySetmeal.getName();
        //可以和原来的一致，但是不能重复其他的
        if ((!code.equals(ocode) && checkCode(code)) || (!name.equals(oname) && checkName(name))) {
            throw new BusinessException("套餐名或编码已经存在");
        }
        //编辑原套餐
        setmealMapper.updateById(setmeal);
        //删除中间表关联数据
        LambdaQueryWrapper<SetmealCheckgroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetmealCheckgroup::getSetmealId, setmeal.getId());
        setMealAndCheckGroupMapper.delete(wrapper);
        //添加关系表
        if (checkgroupIds != null && checkgroupIds.length > 0) {
            for (Integer checkgroupId : checkgroupIds) {
                SetmealCheckgroup setmealCheckgroup = new SetmealCheckgroup();
                setmealCheckgroup.setSetmealId(setmeal.getId());
                setmealCheckgroup.setCheckgroupId(checkgroupId);
                setMealAndCheckGroupMapper.insert(setmealCheckgroup);
            }
        }

    }

    //    删除套餐
    @Override
    public void delete(Integer id) throws BusinessException {

        RedisUtil.delete(redisTemplate, RedisConstant.QUERY_SETMEALS_KEY);

//        删除中间表
        setMealAndCheckGroupMapper.delete(new LambdaQueryWrapper<SetmealCheckgroup>().eq(SetmealCheckgroup::getSetmealId, id));

//        删除套餐
        setmealMapper.deleteById(id);
    }

    //    查询所有套餐
    @Override
    public List<Setmeal> findAll() throws BusinessException {
        String key = RedisConstant.QUERY_SETMEALS_KEY;
        ValueOperations opsForValue = redisTemplate.opsForValue();
        List<Setmeal> setmeals = null;
        if (redisTemplate.hasKey(key)) {
            setmeals = (List<Setmeal>) opsForValue.get(key);
        } else {
            setmeals = setmealMapper.selectList(null);
            opsForValue.set(key, setmeals);
        }

        return setmeals;
    }


    //    查看详情
    @Override
    public Setmeal findSeteamDetailById(Integer id) throws BusinessException {
        return setmealMapper.findSeteamDetailById(id);
    }


    /**
     *
     * 统计套餐预约数量
     */

    @Override
    public List<Map<String, Object>> findSetmealCount() throws BusinessException {



        List<Map<String, Object>> list = setmealMapper.findSetmealCount();
        log.info("套餐预约量数据",list);
        return list;
    }

    /**
     * 检查名称是否存在
     *
     * @param name
     */
    private boolean checkName(String name) {
        Integer count = setmealMapper.selectCount(
                new LambdaQueryWrapper<Setmeal>().eq(Setmeal::getName, name)
        );
        return count > 0;
    }

    /**
     * 检查编码是否存在
     *
     * @param code
     */
    private boolean checkCode(String code) {
        Integer count = setmealMapper.selectCount(
                new LambdaQueryWrapper<Setmeal>().eq(Setmeal::getCode, code)
        );
        return count > 0;
    }

}

